/**
 * SHT30温湿度传感器驱动
 * 使用I2C接口通信
 */

#include "sht30.h"
#include "stdio.h"

// I2C超时定义
#define I2C_TIMEOUT 10000

// 延时函数
static void Delay_us(uint32_t us) {
    uint32_t count = us * 8; // 72MHz时钟
    while (count--) {
        __NOP();
    }
}

// 等待I2C事件
static uint8_t I2C_WaitEvent(I2C_TypeDef* I2Cx, uint32_t event) {
    uint32_t timeout = I2C_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, event)) {
        if (--timeout == 0) return 0;
    }
    return 1;
}

// SHT30初始化
void SHT30_Init(void) {
    // 发送软复位命令
    SHT30_SoftReset();
    
    // 延时等待传感器初始化
    Delay_us(2000);
    
    printf("SHT30温湿度传感器初始化完成\r\n");
}

// SHT30软复位
uint8_t SHT30_SoftReset(void) {
    uint8_t cmd_high = (SHT30_CMD_SOFTRESET >> 8) & 0xFF;
    uint8_t cmd_low = SHT30_CMD_SOFTRESET & 0xFF;
    
    // 发送起始信号
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    // 发送设备地址
    I2C_Send7bitAddress(I2C1, SHT30_I2C_ADDR, I2C_Direction_Transmitter);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return 0;
    
    // 发送命令高字节
    I2C_SendData(I2C1, cmd_high);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    
    // 发送命令低字节
    I2C_SendData(I2C1, cmd_low);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    
    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);
    
    return 1;
}

// 读取温湿度数据
uint8_t SHT30_Read(float *temperature, float *humidity) {
    uint8_t tx_data[2];
    uint8_t rx_data[6];
    uint16_t temp_raw, humi_raw;
    
    // 发送测量命令 (高精度，时钟拉伸禁用)
    tx_data[0] = (SHT30_CMD_MEAS_CLOCKSTR_H >> 8) & 0xFF;
    tx_data[1] = SHT30_CMD_MEAS_CLOCKSTR_H & 0xFF;
    
    // 发送起始信号
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    // 发送设备地址
    I2C_Send7bitAddress(I2C1, SHT30_I2C_ADDR, I2C_Direction_Transmitter);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return 0;
    
    // 发送命令
    I2C_SendData(I2C1, tx_data[0]);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    I2C_SendData(I2C1, tx_data[1]);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    
    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);
    
    // 等待测量完成 (15ms)
    Delay_us(15000);
    
    // 读取数据
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    I2C_Send7bitAddress(I2C1, SHT30_I2C_ADDR, I2C_Direction_Receiver);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) return 0;
    
    // 读取6个字节数据
    for (int i = 0; i < 6; i++) {
        if (i == 5) {
            // 最后一个字节不发送ACK
            I2C_AcknowledgeConfig(I2C1, DISABLE);
        }
        
        if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) return 0;
        rx_data[i] = I2C_ReceiveData(I2C1);
    }
    
    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);
    // 重新使能ACK
    I2C_AcknowledgeConfig(I2C1, ENABLE);
    
    // CRC校验
    if (!SHT30_CheckCrc(&rx_data[0], 2, rx_data[2])) return 0;
    if (!SHT30_CheckCrc(&rx_data[3], 2, rx_data[5])) return 0;
    
    // 解析数据
    temp_raw = (rx_data[0] << 8) | rx_data[1];
    humi_raw = (rx_data[3] << 8) | rx_data[4];
    
    // 计算温湿度值
    *temperature = -45.0 + 175.0 * temp_raw / 65535.0;
    *humidity = 100.0 * humi_raw / 65535.0;
    
    return 1;
}

// CRC8校验
uint8_t SHT30_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum) {
    uint8_t crc = 0xFF;
    uint8_t bit = 0;
    uint8_t byteCtr;
    
    // 计算CRC
    for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr) {
        crc ^= (data[byteCtr]);
        for (bit = 8; bit > 0; --bit) {
            if (crc & 0x80) {
                crc = (crc << 1) ^ 0x31;
            } else {
                crc = (crc << 1);
            }
        }
    }
    
    return (crc == checksum);
}

// 读取状态寄存器
uint8_t SHT30_ReadStatus(uint16_t *status) {
    uint8_t cmd_high = (SHT30_CMD_READSTATUS >> 8) & 0xFF;
    uint8_t cmd_low = SHT30_CMD_READSTATUS & 0xFF;
    uint8_t rx_data[3];
    
    // 发送读取状态命令
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    I2C_Send7bitAddress(I2C1, SHT30_I2C_ADDR, I2C_Direction_Transmitter);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) return 0;
    
    I2C_SendData(I2C1, cmd_high);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    I2C_SendData(I2C1, cmd_low);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return 0;
    
    // 重新启动读取数据
    I2C_GenerateSTART(I2C1, ENABLE);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) return 0;
    
    I2C_Send7bitAddress(I2C1, SHT30_I2C_ADDR, I2C_Direction_Receiver);
    if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) return 0;
    
    // 读取3个字节
    for (int i = 0; i < 3; i++) {
        if (i == 2) {
            I2C_AcknowledgeConfig(I2C1, DISABLE);
        }
        if (!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) return 0;
        rx_data[i] = I2C_ReceiveData(I2C1);
    }
    
    I2C_GenerateSTOP(I2C1, ENABLE);
    I2C_AcknowledgeConfig(I2C1, ENABLE);
    
    // CRC校验
    if (!SHT30_CheckCrc(&rx_data[0], 2, rx_data[2])) return 0;
    
    *status = (rx_data[0] << 8) | rx_data[1];
    return 1;
}
